<?php
/**
 * 后台管理基类控制器
 * Created by PhpStorm.
 * User: crstu
 * Date: 2016/4/25
 * Time: 16:47
 */

namespace backend\commands;

use yii;
use yii\web\Controller;
use yii\helpers\Url;
use common\models\DAO\AdminLog;
use common\models\DAO\AdminPower;
use yii\data\ActiveDataProvider;

class BaseAdminController extends Controller
{

    protected $admin_id; //管理员ID
    protected $admin_name; //管理员名称
    protected $admin_role_id; //管理员角色ID
    protected $adminLog; //管理员日志

    public $model;
    public $modelTitle = '';

    /*
     * 入口白名单
     * 注：符合此名单的，不进行登录检测
     * 结构：[controllerID, actionID], * 代表任意
     */
    public $access_white_list = [
        ['*', 'ajax-validate'],
        ['login', '*'],
        ['login', 'index'],
        ['login', 'captcha'],
        ['login', 'out'],
        ['public', '*'],
        ['x-relation', '*'],
    ];

    /*
     * 权限白名单
     * 注：凡是符合此选项的，不进行权限检查
     */
    public $power_white_list = [
        ['public', '*'],
        ['api', '*'],
        ['index', 'index'],
        ['index', 'welcome'],
        ['admin', 'change-profile'],
        ['admin', 'change-password'],
        ['upload', '*'],
    ];

    /**
     * 后台全局初始化
     * 检查登陆
     * @param \yii\base\Action $action 方法对象
     * @return bool|\yii\web\Response
     */
    public function beforeAction($action)
    {

        Yii::$app->language = 'zh-CN';

        $this->adminLog = new AdminLog();

        $controller_action_ids = [$action->controller->id, $action->id];

        //检测过滤白名单
        if($this->filterWhiteList($controller_action_ids, $this->access_white_list)){
            return true;
        }else{
            $this->admin_id = Yii::$app->session->get('ADMIN_ID');
            if(empty($this->admin_id)){
                $this->redirect(['/login'])->send();
                return false;
            }else{
                //检查最后操作时间，如果超时，则自动退出
                $this->checkLastActionTime();

                $this->admin_name = Yii::$app->session->get('ADMIN_NAME');
                $this->admin_role_id    = Yii::$app->session->get('ADMIN_ROLE_ID');

                //初始化菜单
//                $this->admin_menu = (new AdminService)->buildMenu($this->admin_role_id);

                //检查权限
                if($this->admin_role_id == 1 || $this->filterWhiteList($controller_action_ids, $this->power_white_list)){
                    return true;
                }else{
                    $allow = (new AdminPower())->checkPower($this->admin_role_id, $action->controller->id, $action->id);
                    if(empty($allow)){
                        $this->noPower();
                        exit;
                    }else{
                        return true;
                    }
                }
            }
        }
    }

    /**
     * 检查最后操作时间
     */
    private function checkLastActionTime(){
        $session = Yii::$app->session;
        $last_action_time = $session->get('LAST_ACTION_TIME');
        $session->set('LAST_ACTION_TIME', time());
        if(empty($last_action_time)){
            $session->set('LAST_ACTION_TIME', time());
        }else{
            if(( time() - $last_action_time ) > Yii::$app->params['last_action_time']){
                $this->redirect(['login/out']);
            }
        }
    }


    /**
     * 白名单过滤工具
     * @param $input array
     * @param $list array
     * @return bool
     */
    private function filterWhiteList($input, $list){
        if(is_array($input)){
            if(!empty($input[0]) || !empty($input[1]) || $input[0] != '*' || $input[1] != '*'){
                foreach($list as $v){
                    if($v[0] == '*' || $v[0] == $input[0]){
                        if($v[1] == '*' || $v[1] == $input[1])
                            return true;
                    }
                }
            }
        }
        return false;
    }


    /**
     * 操作日志的加入
     * @param yii\base\Action $action
     * @param mixed $result
     * @return mixed
     */
    public function afterAction($action, $result){
        $result = parent::afterAction($action, $result);
        $admin_id = \Yii::$app->session->get('ADMIN_ID');
        if($admin_id > 1 && !in_array($action->id, ['ajax-validate', 'index', 'list'])){
            (new AdminLog)->addLog($admin_id, '', $action->controller->id, $action->id, serialize($_GET), serialize($_POST));
        }
        return $result;
    }


    /*
     * 重新封装render，将PJAX请求与普通请求区分开
     */
    public function render($view, $params = [])
    {
        if(empty($_SERVER['HTTP_X_PJAX'])){
            $content = $this->getView()->render($view, $params, $this);
            return $this->renderContent($content);
        }else{
            return $this->getView()->renderAjax($view, $params, $this);
        }
    }


    /**
     * Message页面
     * @param string $title 标题
     * @param string $class 提示框样式：class info warning danger
     * @param string $body 消息主内容
     * @param string $url 跳转地址
     * @return string
     */
    public function renderMessage($title, $url, $class = null, $content = '')
    {
        $link = [];
        if($url == -1)
        {
            $link['title'] = '返 回';
            $link['url']   = "javascript:window.history.go(-1)";//后退
            $link['class'] = 'dark';
        }
        elseif($url == 'referrer' || $url == 'r')//获取Session里存储的请求来源地址
        {
            $link['title'] = '返 回';
            $link['url']   = Yii::$app->session->get('REFERRER_URL');
            $link['class'] = 'dark';
        }
        elseif(is_string($url) && !strstr($url, 'http'))//判断是否是数组或者字符串
        {
            $link['title'] = '跳 转';
            $link['url']   = Url::to([$url]);
            $link['class'] = 'blue';
        }
        elseif(is_array($url))
        {
            $link['title'] = '跳 转';
            $link['url']   = Url::to($url);
            $link['class'] = 'blue';
        }
        else
        {
            $link['title'] = '跳 转';
            $link['url']   = $url;
            $link['class'] = 'blue';
        }

        if(empty($class) || !in_array($class, ['info', 'danger', 'warning', 'success'])) $class = 'info';

        $content = empty($content) ? '&nbsp;' : $content;

        //内容换行
        if(is_array($content)){
            foreach ($content as $key => $val){
                if(is_array($val)){
                    $content = implode("<br/>",$val);
                }else{
                    $content = implode("<br/>",$content);
                }
            }
        }


        return $this->render('/public/message', ['title' => $title, 'link'=>$link, 'class'=>$class, 'content'=>$content]);
    }


    public function renderAlert($body, $url, $class = null)
    {
        if($url == -1){
            $url = "javascript:window.history.go(-1)";//后退
        }elseif($url == 'referrer' || $url == 'r'){//获取Session里存储的请求来源地址
            $url = Yii::$app->session->get('REFERRER_URL');
        }elseif(is_string($url) && !strstr($url, 'http')){//判断是否是数组或者字符串
            $url = Url::to([$url]);
        }elseif(is_array($url)){
            $url = Url::to($url);
        }
        if(empty($class) || !in_array($class, ['info', 'danger', 'warning', 'success'])) $class = 'info';
        if(is_array($body))
            $body = implode('<br/>', $body);

        return $this->render('/public/alert', ['url'=>$url, 'class'=>$class, 'body'=>$body]);
    }


    /**
     * Confirm提示页面
     * @param string $message 对话框问题
     * @param string $url 继续请求地址
     * @return string
     */
    public function renderConfirm($message, $url)
    {
        if(is_string($url) && !strstr($url, 'http')){//判断是否是数组或者字符串
            $url = Url::to([$url]);
        }elseif(is_array($url)){
            $url = Url::to($url);
        }
        return $this->render('/public/confirm', ['url'=>$url, 'message'=>$message]);
    }


    /**
     * 检查用户权限
     * @return array
     */
    public function checkPower($action){

        $adminPower = new AdminPower();
        return $adminPower->checkPower($this->admin_role_id, $action->controller->id, $action->id);
    }


    /**
     * JSON 返回方法
     * 可以只传入一个数组，则次函数会将传入的数组直接以Json的格式返回
     * @param int|array $status
     * @param null $data
     * @param string $message
     */
    public function renderJson($status=null, $data=null, $message=""){
        if($status === null && $data === null){
            $output = "";
        }else{
            if(!empty($status) && is_array($status)){
                $output = $status;
            }else{
                $output = array(
                    'status' => intval($status),
                    'data' => $data,
                    'message' => $message,
                );
            }
        }
        //header("Content-type: 'application/json;charset=UTF-8'");
        echo json_encode($output);
        exit;
    }


    /**
     * 公共Ajax验证方法
     * @return array|bool
     */
    public function actionAjaxValidate(){
        return $this->ajaxValidate($this->model);
    }


    /*
     * 通用ActiveForm的Ajax验证
     * @param object $model 模型对象
     */
    protected function ajaxValidate($model){
        if(\Yii::$app->request->isAjax && $model->load(\Yii::$app->request->post())) {
            \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
            return  \common\widgets\ActiveForm::validate($model);
        }
        return false;
    }


    /**
     * 将中国时间格式转化成时间戳
     * @param string $date 2015年7月15日 12点12分17秒
     * @return int timestamp
     */
    protected function cnDateToTime($date){
        return strtotime(str_replace(['年', '月'], '-', str_replace(['点', '时', '秒'], ':', str_replace(['日', '秒'], '', $date))));
    }

    /**
     * 检测是否是移动设备进入
     * @return bool
     */
    protected function isMobile()
    {
        // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
        if (isset ($_SERVER['HTTP_X_WAP_PROFILE']))
        {
            return true;
        }
        // 如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
        if (isset ($_SERVER['HTTP_VIA']))
        {
            // 找不到为flase,否则为true
            return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
        }
        // 脑残法，判断手机发送的客户端标志,兼容性有待提高
        if (isset ($_SERVER['HTTP_USER_AGENT']))
        {
            $clientkeywords = array ('nokia',
                'sony', 'ericsson', 'mot', 'samsung', 'htc', 'sgh', 'lg', 'sharp', 'sie-', 'philips', 'panasonic',
                'alcatel', 'lenovo', 'iphone', 'ipod', 'blackberry', 'meizu', 'android', 'netfront', 'symbian',
                'ucweb', 'windowsce', 'palm', 'operamini', 'operamobi', 'openwave', 'nexusone', 'cldc', 'midp',
                'wap', 'mobile'
            );
            // 从HTTP_USER_AGENT中查找手机浏览器的关键字
            if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT'])))
            {
                return true;
            }
        }
        // 协议法，因为有可能不准确，放到最后判断
        if (isset ($_SERVER['HTTP_ACCEPT']))
        {
            // 如果只支持wml并且不支持html那一定是移动设备
            // 如果支持wml和html但是wml在html之前则是移动设备
            if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html'))))
            {
                return true;
            }
        }
        return false;
    }

    /*
     * 没有权限的页面显示输出
     */
    protected function noPower(){
        echo $this->renderMessage('您没有此权限！', -1, 'danger');
    }


    /**
     * 基本修改/添加方法
     * @param array $option ['id'=>$id, 'model'=>$model, 'url'=>$url, 'template'=>$template]
     * @return string
     */
    protected function CommonBaseEdit($option = [])
    {
        $id       = (isset($option['id']) && !empty($option['id']) ) ? $option['id'] : 0;
        $template = (isset($option['template']) && !empty($option['template']) ) ? $option['template'] : 'edit';
        $model    = (isset($option['model']) && !empty($option['model']) ) ? $option['model'] : $this->model;
        $url      = (isset($option['url']) && !empty($option['url']) ) ? $option['url'] : $this->action->controller->id . '/list';

        if ($id > 0) {
            $scenario = (isset($option['scenario']) && !empty($option['scenario']) ) ? $option['scenario'] : 'edit';
            $model = $model::findOne($id);
            $model->setScenario($scenario);
            $this->view->title = '修改' . $this->modelTitle;
        } else {
            $scenario = (isset($option['scenario']) && !empty($option['scenario']) ) ? $option['scenario'] : 'add';
            $model->setScenario($scenario);
            $this->view->title = '添加' . $this->modelTitle;
        }
        $request = \Yii::$app->request;
        if ($request->isPost) {
            if ($model->load($request->post()) && $model->save()) {
                return $this->renderMessage('保存成功！', $url, 'success');
            } else {
                return $this->renderMessage('保存失败！', -1, 'danger',$model->getErrors());
            }
        } else {
            return $this->render($template, ['model' => $model]);
        }
    }


    /**
     * 公共基本列表方法
     * @param array $option ['model'=>$model, 'template'=>$template]
     * @return string
     */
    protected function CommonBaseList($options = [])
    {
        $model    = empty($options['model']) ? $this->model : $options['model'];
        $template = empty($options['template']) ? 'list' : $options['model'];

        $query = $model->find();
        if(isset($options['where']))
            $query->andWhere($options['where']);

        $model->setScenario('list');
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'pagination' => [
                'pageSize' => 30
            ],
            'sort' => [
                'defaultOrder' => [
                    'id' => SORT_ASC,
                ]
            ],
        ]);

        return $this->render($template, ['model' => $model, 'dataProvider' => $dataProvider]);
    }

    /**
     * 公共高级列表方法
     * @param array $option ['model'=>$model, 'searchModel' => $searchModel, 'template'=>$template]
     * @return string
     */
    protected function CommonAdvanceList($options = []){
        $model    = empty($options['model']) ? $this->model : $options['model'];
        $template = empty($options['template']) ? 'list' : $options['template'];
        $where    = empty($options['where']) ? [] : $options['where'];
        if(empty($options['searchModel'])){
            return $this->renderMessage('缺少SearchModel参数！', -1, 'danger');
        }else{
            $searchModel = $options['searchModel'];
        }

        unset($options['model']);
        unset($options['template']);
        unset($options['searchModel']);

        $dataProvider = $searchModel->search(Yii::$app->request->get(), $where);
        return $this->render(
            $template,
            [
                'model' => $model,
                'searchModel' => $searchModel,
                'dataProvider' => $dataProvider,
            ]
        );
    }
}